package com.jf.cloud.order.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.jf.cloud.api.delivery.feign.StationFeignClient;
import com.jf.cloud.api.delivery.vo.StationVO;
import com.jf.cloud.api.order.constant.OrderStatus;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.order.dto.OrderVirtualInfoDTO;
import com.jf.cloud.common.order.vo.OrderVirtualInfoVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.rocketmq.config.RocketMqConstant;
import com.jf.cloud.order.constant.RefundStatusEnum;
import com.jf.cloud.order.mapper.OrderMapper;
import com.jf.cloud.order.mapper.OrderVirtualInfoMapper;
import com.jf.cloud.order.model.Order;
import com.jf.cloud.order.model.OrderVirtualInfo;
import com.jf.cloud.order.service.OrderVirtualInfoService;
import com.jf.cloud.order.vo.OrderShopVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 订单虚拟商品信息
 *
 * @author zz
 * @date 2023-03-09 19:55:55
 */

@Service
public class OrderVirtualInfoServiceImpl implements OrderVirtualInfoService {

    @Autowired
    private OrderVirtualInfoMapper orderVirtualInfoMapper;
    @Autowired
    private StationFeignClient stationFeignClient;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RocketMQTemplate orderReceiptTemplate;

    @Override
    public PageVO<OrderVirtualInfo> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> orderVirtualInfoMapper.list());
    }

    @Override
    public OrderVirtualInfo getById(Long id) {
        return orderVirtualInfoMapper.getById(id);
    }

    @Override
    public void save(OrderVirtualInfo orderVirtualInfo) {
        orderVirtualInfoMapper.save(orderVirtualInfo);
    }

    @Override
    public void update(OrderVirtualInfoVO orderVirtualInfo) {
        orderVirtualInfoMapper.update(orderVirtualInfo);
    }

    @Override
    public void deleteById(Long id) {
        orderVirtualInfoMapper.deleteById(id);
    }

    @Override
    public void saveBatch(List<OrderVirtualInfo> orderVirtualInfoList) {
        orderVirtualInfoMapper.saveBatch(orderVirtualInfoList);
    }

    /**
     * 添加下虚拟商品的信息
     *
     * @param order        订单信息
     * @param orderShopVO 用于前端展示的订单信息
     * @param stationId 门店id
     */
    @Override
    public void handlerVirtualProdOrder(Order order, OrderShopVO orderShopVO, Long stationId) {
        orderShopVO.setOrderMold(order.getOrderMold());
        orderShopVO.setWriteOffStart(order.getWriteOffStart());
        orderShopVO.setWriteOffEnd(order.getWriteOffEnd());
        orderShopVO.setWriteOffNum(order.getWriteOffNum());
        orderShopVO.setWriteOffMultipleCount(order.getWriteOffMultipleCount());
        if (Objects.equals(order.getOrderItems().get(0).getIsRefund(), 0)) {
            orderShopVO.setCanAllRefund(false);
            orderShopVO.setCanRefund(false);
        }

        // 卡券信息
        List<OrderVirtualInfoVO> virtualInfoList = getByOrderIdAndStationId(order.getOrderId(), stationId);
        boolean flag = Objects.equals(order.getStatus(), OrderStatus.WAIT_GROUP.value()) || Objects.equals(order.getStatus(), OrderStatus.UNPAY.value()) ;
        if (CollectionUtil.isNotEmpty(virtualInfoList) && !flag) {
            orderShopVO.setVirtualInfoList(virtualInfoList);
            orderShopVO.setTotalNum(virtualInfoList.size());
        }
    }

    @Override
    public List<OrderVirtualInfoVO> getByOrderIdAndStationId(Long orderId, Long stationId) {
        return orderVirtualInfoMapper.getByOrderIdAndStationId(orderId, stationId);
    }

    @Override
    public List<OrderVirtualInfoVO> getByOrderIdAndShopId(Long orderId, Long shopId, Integer isWriteOff){
        return orderVirtualInfoMapper.getByOrderIdAndShopId(orderId, shopId, isWriteOff);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderWriteOffByOrderId(OrderVirtualInfoDTO orderVirtualInfoDTO, Order order, Long stationId) {
        Date date = new Date();
        List<OrderVirtualInfoVO> orderVirtualInfoList = checkInfoAndGetVirtualInfo(order, stationId, date);
        List<OrderVirtualInfoVO> updateList = new ArrayList<>();
        // 核销码是否存在
        if (Objects.nonNull(orderVirtualInfoDTO) && StrUtil.isNotBlank(orderVirtualInfoDTO.getWriteOffCode())) {
            boolean isExist = false;
            for (OrderVirtualInfoVO orderVirtualInfo : orderVirtualInfoList) {
                if (StrUtil.equals(orderVirtualInfoDTO.getWriteOffCode(), orderVirtualInfo.getWriteOffCode())) {
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                // 卡券不存在或者已核销
                throw new LuckException("核销码错误");
            }
        }
        // 如果是多次核销且无限次则无需进行核销
        if (Objects.equals(order.getWriteOffNum(), -1) &&
                (Objects.equals(order.getWriteOffMultipleCount(), -1) || Objects.isNull(order.getWriteOffMultipleCount()))) {
            return true;
        }
        // 是否全部核销完成
        boolean isAllWriteOff;
        // 核销码存在时表示直接是核销码核销，否则直接是整单核销
        if (Objects.nonNull(orderVirtualInfoDTO) && StrUtil.isNotBlank(orderVirtualInfoDTO.getWriteOffCode())) {
            isAllWriteOff = orderVirtualInfoList.size() < 2;
            for (OrderVirtualInfoVO orderVirtualInfo : orderVirtualInfoList) {
                if (StrUtil.equals(orderVirtualInfoDTO.getWriteOffCode(), orderVirtualInfo.getWriteOffCode())) {
                    orderVirtualInfo.setWriteOffTime(date);
                    orderVirtualInfo.setStationId(stationId);
                    // 多次核销次数还没到
                    if (Objects.equals(order.getWriteOffNum(), -1) && 0 < orderVirtualInfo.getWriteOffMultipleCount() - 1) {
                        orderVirtualInfo.setWriteOffMultipleCount(orderVirtualInfo.getWriteOffMultipleCount() - 1);
                        isAllWriteOff = false;
                        updateList.add(orderVirtualInfo);
                        continue;
                    }
                    orderVirtualInfo.setIsWriteOff(1);
                    updateList.add(orderVirtualInfo);
                    break;
                }
            }
        } else {
            isAllWriteOff = true;
            for (OrderVirtualInfoVO orderVirtualInfo : orderVirtualInfoList) {
                orderVirtualInfo.setStationId(stationId);
                orderVirtualInfo.setWriteOffTime(date);
                // 多次核销次数还没到
                if (Objects.equals(order.getWriteOffNum(), -1) && 0 < orderVirtualInfo.getWriteOffMultipleCount() - 1) {
                    orderVirtualInfo.setWriteOffMultipleCount(orderVirtualInfo.getWriteOffMultipleCount() - 1);
                    isAllWriteOff = false;
                    updateList.add(orderVirtualInfo);
                    continue;
                }
                orderVirtualInfo.setIsWriteOff(1);
                updateList.add(orderVirtualInfo);
            }
        }
        updateList.forEach(this::update);
        Order updateOrder = new Order();
        updateOrder.setOrderId(order.getOrderId());
        updateOrder.setUpdateTime(date);
        // 全部提货完成就直接确认收货
        if (isAllWriteOff) {
            updateOrder.setWriteOffStatus(1);
            if (Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value())) {
                updateOrder.setStatus(OrderStatus.SUCCESS.value());
                updateOrder.setFinallyTime(new Date());
                // 开启事务消息，添加积分
                TransactionSendResult transactionSendResult = orderReceiptTemplate.sendMessageInTransaction(RocketMqConstant.ORDER_RECEIPT_TOPIC, new GenericMessage<>(updateOrder.getOrderId()), null);
                if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
                    throw new LuckException(ResponseEnum.EXCEPTION);
                }
            }

            orderMapper.update(updateOrder);
        }
        return true;
    }


    private List<OrderVirtualInfoVO> checkInfoAndGetVirtualInfo(Order orderDb, Long stationId, Date date) {
        if (Objects.nonNull(stationId)) {
            StationVO station = stationFeignClient.getStation(stationId).getData();
            if (!Objects.equals(station.getStatus(), 1)) {
                // 该自提点未在营业状态
                throw new LuckException("该自提点未在营业状态");
            }
        }
        boolean isRefund = Objects.equals(orderDb.getRefundStatus(), RefundStatusEnum.APPLY.value())
                || Objects.equals(orderDb.getRefundStatus(), RefundStatusEnum.SUCCEED.value())
                || Objects.equals(orderDb.getRefundStatus(), RefundStatusEnum.PARTIAL_SUCCESS.value());
        if (Objects.nonNull(orderDb.getRefundStatus()) && isRefund) {
            // 订单退款中，无法核销
            throw new LuckException("订单"+orderDb.getOrderId()+"退款中，无法核销");
        }
        if (Objects.equals(orderDb.getWriteOffNum(), 0)) {
            // 订单无需核销
            throw new LuckException("订单无需核销");
        }
        // 查询出未核销的卡券
        List<OrderVirtualInfoVO> orderVirtualInfoList = getByOrderIdAndShopId(orderDb.getOrderId(), orderDb.getShopId(), 0);
        if (CollectionUtils.isEmpty(orderVirtualInfoList)) {
            // 卡券不存在或者已核销
            throw new LuckException("卡券不存在或者已核销");
        }
        if (DateUtil.compare(orderDb.getWriteOffStart(), date) > 0) {
            // 卡券未到使用时间或已过期
            throw new LuckException("卡券未到使用时间或已过期");
        }
        if (Objects.nonNull(orderDb.getWriteOffEnd()) && DateUtil.compare(date, orderDb.getWriteOffEnd()) > 0) {
            // 卡券未到使用时间或已过期
            throw new LuckException("卡券未到使用时间或已过期");
        }
        return orderVirtualInfoList;
    }

    @Override
    public List<OrderVirtualInfoVO> getByOrderIdAndCode(Long orderId, String code){
        return orderVirtualInfoMapper.getByOrderIdAndCode(orderId, code);
    }

}
